﻿using ZYCommon;
using Microsoft.VisualBasic.Vsa;
using Microsoft.Vsa;
using System;
using System.Collections;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using TextEditor.TextDocument.Document;

namespace TextEditor
{    
    public class ZYVBScriptEngine : VsaEngine
    {
        public bool HasUserInterface = false;
        //private IVsaCodeItem myCodeItem = null;
        //private IVsaCodeItem myGlobalCodeItem = null;
        private Hashtable myMethodTable = new Hashtable();
        public ZYTextDocument myOwnerDocument = null;
        private ZYTextDocumentVsaSite myVsaSite = new ZYTextDocumentVsaSite();
        private string strScriptText = null;

        public ZYVBScriptEngine()
        {
            //base.RootMoniker = "leadroninc://ZYTextDocument//script";
            //base.Site = this.myVsaSite;
            //base.InitNew();
            //base.RootNamespace = "TextEditor";
            //base.GenerateDebugInfo = true;
            //this.AddRefrence("system.dll");
            //this.AddRefrence("mscorlib.dll");
            //this.AddRefrence("system.drawing.dll");
            //this.AddRefrence("system.xml.dll");
            //this.AddRefrence("system.data.dll");
            //this.AddRefrence("system.windows.forms.dll");
            //this.AddRefrence("Microsoft.VisualBasic.dll");
            //this.AddGlobalItem("document", "object");
            //this.AddGlobalItem("eventobj", "object");
            //this.AddGlobalItem("emrvb", "object");
            //this.AddGlobalItem("dbconnection", "object");
            //this.myCodeItem = base.Items.CreateItem("UserCode", VsaItemType.Code, VsaItemFlag.None) as IVsaCodeItem;
            //this.myGlobalCodeItem = base.Items.CreateItem("GlobalCode", VsaItemType.Code, VsaItemFlag.None) as IVsaCodeItem;
        }

        private void AddGlobalItem(string strName, string strTypeName)
        {
            //IVsaGlobalItem item = base.Items.CreateItem(strName, VsaItemType.AppGlobal, VsaItemFlag.None) as IVsaGlobalItem;
            //item.TypeString = strTypeName;
        }

        private void AddRefrence(string strDllName)
        {
            try
            {
                ZYErrorReport.Instance.DebugPrint("向脚本引擎添加引用" + strDllName);
                //IVsaReferenceItem item = base.Items.CreateItem(strDllName, VsaItemType.Reference, VsaItemFlag.None) as IVsaReferenceItem;
                //item.AssemblyName = strDllName;
            }
            catch (Exception exception)
            {
                ZYErrorReport.Instance.SourceException = exception;
                ZYErrorReport.Instance.SourceObject = this;
                ZYErrorReport.Instance.UserMessage = "向脚本引擎添加引用 " + strDllName + " 错误";
                ZYErrorReport.Instance.MemberName = "ZYVBScriptEngine.AddRefrence";
                ZYErrorReport.Instance.ReportError();
            }
        }

        public void AppendScript(string strScript)
        {
            if (this.strScriptText == null)
            {
                this.strScriptText = strScript;
            }
            else
            {
                this.strScriptText = this.strScriptText + strScript;
            }
        }

        public bool CompileZYVB()
        {
            if (StringCommon.isBlankString(this.strScriptText))
            {
                this.StopScript();
                return false;
            }
            //this.myCodeItem.SourceText = "Option Strict Off\r\nImports System \r\nImports System.Xml \r\nImports System.Data\r\nImports System.Windows.Forms\r\nImports System.Drawing \r\nImports Microsoft.VisualBasic\r\n'Imports ZYCommon\r\n'Imports TextEditor \r\nModule UserCode\r\n" + this.strScriptText + "\r\nEnd Module";
            //if (base.Compile())
            //{
            //    ZYErrorReport.Instance.DebugPrint("编译ZYVB代码成功，代码为\r\n" + this.myCodeItem.SourceText);
            //    return true;
            //}
            //ZYErrorReport.Instance.DebugPrint("编译ZYVB代码失败，代码为\r\n" + this.myCodeItem.SourceText);
            return false;
        }

        public MethodInfo GetScriptMethod(string strName)
        {
            if (strName != null)
            {
                strName = strName.Trim().ToLower();
                if (strName.Length > 0)
                {
                    return (this.myMethodTable[strName] as MethodInfo);
                }
            }
            return null;
        }

        public object InvokeScriptMethod(MethodInfo myMethod, object obj, object[] Parameters)
        {
            if (myMethod != null)
            {
                try
                {
                    if (this.myOwnerDocument != null)
                    {
                        this.myOwnerDocument.BeginUpdate();
                        this.myOwnerDocument.BeginContentChangeLog();
                    }
                    object obj2 = null;
                    try
                    {
                        ZYErrorReport.Instance.DebugPrint("执行脚本 " + myMethod.Name);
                        obj2 = myMethod.Invoke(obj, Parameters);
                    }
                    catch (Exception exception)
                    {
                        string text = "运行脚本[" + myMethod.Name + "]错误!\r\n" + exception.ToString();
                        if ((this.myOwnerDocument == null) || this.myOwnerDocument.Info.ShowScriptError)
                        {
                            MessageBox.Show(null, text, "脚本错误", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                            this.HasUserInterface = true;
                        }
                        ZYErrorReport.Instance.DebugPrint(text);
                    }
                    if (this.myOwnerDocument != null)
                    {
                        this.myOwnerDocument.EndContentChangeLog();
                        this.myOwnerDocument.EndUpdate();
                    }
                    return obj2;
                }
                catch (Exception exception2)
                {
                    ZYErrorReport.Instance.SourceException = exception2;
                    ZYErrorReport.Instance.SourceObject = this;
                    ZYErrorReport.Instance.MemberName = "InvokeScriptMethod";
                    ZYErrorReport.Instance.UserMessage = "运行脚本[" + myMethod.Name + "]错误!";
                    ZYErrorReport.Instance.ShowErrorDialog();
                    this.HasUserInterface = true;
                }
            }
            return null;
        }

        public object InvokeScriptMethod(string strMethodName, object obj, object[] Parameters)
        {
            return this.InvokeScriptMethod(this.GetScriptMethod(strMethodName), obj, Parameters);
        }

        public void SetGolbalScriptCode(string strCode)
        {
            //this.myGlobalCodeItem.SourceText = "Option Strict Off\r\nImports System \r\nImports System.Xml \r\nImports System.Data\r\nImports System.Windows.Forms\r\nImports System.Drawing \r\nImports Microsoft.VisualBasic\r\n'Imports ZYCommon\r\n'Imports TextEditor \r\nModule GlobalCode\r\n" + strCode + "\r\nEnd Module";
        }

        public bool StartScript()
        {
            try
            {
                this.StopScript();
                this.myVsaSite.ZYVB = new ZYVBSystem(this.myOwnerDocument);
                this.myVsaSite.ZYVB.ZYVBEngine = this;
                this.myVsaSite.Document = this.myOwnerDocument;
                if (this.myOwnerDocument != null)
                {
                    this.myVsaSite.ShowErrorMsg = this.myOwnerDocument.Info.ShowScriptCompileError;
                }
                else
                {
                    this.myVsaSite.ShowErrorMsg = true;
                }
                if (this.myOwnerDocument != null)
                {
                    this.myVsaSite.DBConnection = new ZYVBConnection(this.myOwnerDocument.DataSource.DBConn);
                }
                else
                {
                    this.myVsaSite.DBConnection = null;
                }
                if (!this.CompileZYVB())
                {
                    return false;
                }
                base.Run();
                Assembly assembly = base.Assembly;
                if (assembly != null)
                {
                    Type type = assembly.GetType(base.RootNamespace + ".UserCode");
                    if (type != null)
                    {
                        foreach (MethodInfo info in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase))
                        {
                            this.myMethodTable.Add(info.Name.Trim().ToLower(), info);
                        }
                    }
                    type = assembly.GetType(base.RootNamespace + ".GlobalCode");
                    if (type != null)
                    {
                        foreach (MethodInfo info2 in type.GetMethods(BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance | BindingFlags.IgnoreCase))
                        {
                            this.myMethodTable.Add(info2.Name.Trim().ToLower(), info2);
                        }
                    }
                }
                return true;
            }
            catch (Exception exception)
            {
                if ((this.myOwnerDocument == null) || this.myOwnerDocument.Info.ShowScriptError)
                {
                    MessageBox.Show(null, "运行脚本错误\r\n" + exception.ToString(), "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Hand);
                }
            }
            return false;
        }

        public void StopScript()
        {
            this.myMethodTable.Clear();
            if (base.IsRunning)
            {
                base.Reset();
            }
            if (base.IsCompiled)
            {
                base.RevokeCache();
            }
        }

        public ZYVBEventObject EventObj
        {
            get
            {
                return this.myVsaSite.EventObject;
            }
        }

        public ZYTextDocument OwnerDocument
        {
            get
            {
                return this.myOwnerDocument;
            }
            set
            {
                this.myOwnerDocument = value;
            }
        }

        public string ScriptText
        {
            get
            {
                return this.strScriptText;
            }
            set
            {
                this.strScriptText = value;
            }
        }

        public class ZYTextDocumentVsaSite : IVsaSite
        {
            public ZYVBConnection DBConnection = null;
            public ZYTextDocument Document = null;
            public ZYVBSystem ZYVB = null;
            public ZYVBEventObject EventObject = new ZYVBEventObject();
            private Hashtable myObjects = new Hashtable();
            public bool ShowErrorMsg = true;

            public void GetCompiledState(out byte[] pe, out byte[] debugInfo)
            {
                pe = null;
                debugInfo = null;
            }

            public object GetEventSourceInstance(string itemName, string eventSourceName)
            {
                return this.GetInnerObject(itemName);
            }

            public object GetGlobalInstance(string name)
            {
                return this.GetInnerObject(name);
            }

            private object GetInnerObject(string strName)
            {
                switch (strName)
                {
                    case "document":
                        return this.Document;

                    case "eventobj":
                        return this.EventObject;

                    case "emrvb":
                        return this.ZYVB;

                    case "dbconnection":
                        return this.DBConnection;
                }
                return this.myObjects[strName];
            }

            public void Notify(string notify, object info)
            {
            }

            public bool OnCompilerError(IVsaError error)
            {
                return false;
            }

            public Hashtable Objects
            {
                get
                {
                    return this.myObjects;
                }
            }
        }
    }
}

